package com.evaluation_system.service.impl;

import com.evaluation_system.exception.checkerNotExistException;
import com.evaluation_system.exception.commitChainFail;
import com.evaluation_system.exception.queryChainFail;
import com.evaluation_system.exception.zeroPageException;
import com.evaluation_system.mapper.CheckerMapper;
import com.evaluation_system.pojo.DTO.CheckerPageQueryDTO;
import com.evaluation_system.pojo.DTO.FilePageQueryDTO;
import com.evaluation_system.pojo.Result.PageResult;
import com.evaluation_system.pojo.entity.Checker;
import com.evaluation_system.pojo.entity.Uploader;
import com.evaluation_system.pojo.entity.saveFileInfo;
import com.evaluation_system.service.CheckerService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
@Service
public class CheckerServiceImpl implements CheckerService {

    @Autowired
    private CheckerMapper checkermapper;

    public List<saveFileInfo> readFileForChecker(Integer size, Integer page, String filename) {
        try {
            int offset = (page - 1) * size;
            if (filename == null || filename.trim().isEmpty()) {
                return checkermapper.getFileForChecker(size, offset, "");
            } else {
                return checkermapper.getFileForChecker(size, offset, filename);
            }
        } catch (Exception e) {
            throw new zeroPageException("页面为0异常");
        }
    }


    @Override
    public void updateChecker(Integer fileId, Integer checkerId, Integer checked) {
        if(checkermapper.checkerIsTable(checkerId)==0)
            throw new checkerNotExistException("查无此检查用户");

        checkermapper.updateChecker(checked,fileId);
    }

    @Override
    public PageResult<Checker> pageQuery(CheckerPageQueryDTO checkerPageQueryDTO) {
        // 开启分页
        PageHelper.startPage(checkerPageQueryDTO.getPage(), checkerPageQueryDTO.getPageSize());

        // 执行查询
        Page<Checker> page = checkermapper.pageQuery(checkerPageQueryDTO);

        // 封装结果
        return new PageResult<>(page.getTotal(), page.getResult());
    }

    @Override
    public void add(Checker checker) {
        checkermapper.add(checker);

    }

    @Override
    public void update(Checker checker) {
        checkermapper.update(checker);
    }

    @Override
    public void deleteById(Integer id) {
        checkermapper.deleteById(id);

    }

    @Override
    public PageResult<saveFileInfo> getFile1(FilePageQueryDTO filePageQueryDTO) {
        PageHelper.startPage(filePageQueryDTO.getPage(), filePageQueryDTO.getPageSize());

        Page<saveFileInfo> page = checkermapper.getFile1(filePageQueryDTO);

        return new PageResult<>(page.getTotal(), page.getResult());

    }

    @Override
    public String queryBlockChain(Integer fileId) {

        try {
//            String configFile = "src/main/resources/config-example.toml";
//            // 初始化BcosSDK对象
//            BcosSDK sdk = BcosSDK.build(configFile);
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config-example.toml");
            File tempFile = File.createTempFile("config", ".toml");
            Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);

            BcosSDK sdk = BcosSDK.build(tempFile.getAbsolutePath());
            // 获取Client对象，此处传入的群组ID为1
            Client client = sdk.getClient(Integer.valueOf(1));
            // 构造AssembleTransactionProcessor对象，需要传入client对象，CryptoKeyPair对象和abi、binary文件存放的路径。abi和binary文件需要在上一步复制到定义的文件夹中。
            CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair();

            //仅交易和查询
//            AssembleTransactionProcessor transactionProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(client, keyPair, "src/main/resources/abi/", "");

            String abiDirPath = extractAbiDirToTemp();

            AssembleTransactionProcessor transactionProcessor =
                    TransactionProcessorFactory.createAssembleTransactionProcessor(
                            client,
                            keyPair,
                            abiDirPath,
                            ""
                    );
            //查询过程

            List<Object> params = new ArrayList<>();
            params.add(fileId);
            TransactionResponse transactionResponse = transactionProcessor.sendTransactionAndGetResponseByContractLoader(
            "FileCheck","0xbc2da6945cc722da3e31901fb6321234b7425f91","GetCheck", params
            );

            List<Object> returnValues = transactionResponse.getReturnObject();
            String summary="";
            if(returnValues != null){
                if(returnValues.size() == 1){
                     summary = returnValues.get(0).toString();
                }
                else{
                    System.out.println("返回长度不正确");
                }
            }

            return summary;
        } catch (Exception e) {
            System.err.println("执行失败: " + e.getMessage());
            throw new queryChainFail("链上查询失败");
        }

    }

    @Override
    @Transactional
    public Integer commitBlockChain(Integer fileId, Integer checked,String checkerId) {
        try {
//            String configFile = "src/main/resources/config-example.toml";
//            // 初始化BcosSDK对象
//            BcosSDK sdk = BcosSDK.build(configFile);
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config-example.toml");
            File tempFile = File.createTempFile("config", ".toml");
            Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);

            BcosSDK sdk = BcosSDK.build(tempFile.getAbsolutePath());
            // 获取Client对象，此处传入的群组ID为1
            Client client = sdk.getClient(Integer.valueOf(1));
            // 构造AssembleTransactionProcessor对象，需要传入client对象，CryptoKeyPair对象和abi、binary文件存放的路径。abi和binary文件需要在上一步复制到定义的文件夹中。
            CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair();

            //仅交易和查询
//            AssembleTransactionProcessor transactionProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(client, keyPair, "src/main/resources/abi/", "");
            String abiDirPath = extractAbiDirToTemp();

            AssembleTransactionProcessor transactionProcessor =
                    TransactionProcessorFactory.createAssembleTransactionProcessor(
                            client,
                            keyPair,
                            abiDirPath,
                            ""
                    );

            //上链过程：

            //上链数据构造
            List<Object> params = new ArrayList<>();
            params.add(fileId.toString());
            params.add(checked.toString());
            params.add(checkerId);

            //调用合约的上链函数
            TransactionResponse transactionResponse = transactionProcessor.sendTransactionAndGetResponseByContractLoader("FileCheck","0xc244a8bffae6e0ec1ed95c960db43e5fbe8e15f9","InsertCheck", params);

            // 获取交易哈希
            String transactionHash = transactionResponse.getTransactionReceipt().getTransactionHash();
            System.out.println("Transaction Hash: " + transactionHash);

            checkermapper.saveHash2(fileId,transactionHash);

            //打印返回值
            List<Object> returnValues = transactionResponse.getReturnObject();

            if(returnValues != null){
                for(Object returnValue : returnValues){
                    System.out.println("返回值: "+ returnValue.toString());
                }
            }
        } catch (Exception e) {
            System.err.println("执行失败: " + e.getMessage());
            throw new commitChainFail("链上提交失败");
        }
        return 0;
    }

    @Override
    public Checker SelectById(Integer checkerId) {
        return checkermapper.SelectById(checkerId);
    }

    @Override
    public Checker SelectByUserName(String userName) {
        return checkermapper.SelectByUserName(userName);
    }

    public String extractAbiDirToTemp() throws IOException {
        // 1. 创建临时目录
        Path tempDir = Files.createTempDirectory("abi-temp");

        // 2. 定义 abi 和 bin 文件的文件名（不带路径）
        String[] abiFiles = {
                "FileSummary.abi", "FileCheck.abi", "FileScore.abi", "Table.abi"
        };
        String[] binFiles = {
                "FileSummary.bin", "FileCheck.bin", "FileScore.bin", "Table.bin"
        };

        // 3. 拷贝 abi 文件
        for (String fileName : abiFiles) {
            try (InputStream in = getClass().getClassLoader().getResourceAsStream("abi/" + fileName)) {
                if (in == null) {
                    throw new FileNotFoundException("未找到资源文件：abi/" + fileName);
                }
                Files.copy(in, tempDir.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
            }
        }

        // 4. 拷贝 bin 文件
        for (String fileName : binFiles) {
            try (InputStream in = getClass().getClassLoader().getResourceAsStream("bin/" + fileName)) {
                if (in == null) {
                    throw new FileNotFoundException("未找到资源文件：bin/" + fileName);
                }
                Files.copy(in, tempDir.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
            }
        }

        return tempDir.toFile().getAbsolutePath();
    }
}
